﻿using DotNetCore.CAP;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Core.Helpers;
using ZhonTai.Admin.Services;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using ZhonTai.Industry.Contracts.Core.Record;
using ZhonTai.Industry.Core.Consts;
using ZhonTai.Industry.Domain.AlarmRecord;
using ZhonTai.Industry.Domain.WorkStation;
using ZhonTai.Industry.Repositories.WorkParamRecord;
using ZhonTai.Industry.Repositories.WorkStationRecord;
using ZhonTai.Industry.Resources;
using ZhonTai.Industry.Services.AlarmRecord.Dto.Input;
using ZhonTai.Industry.Services.AlarmRecord.Dto.Output;
using ZhonTai.Industry.Services.WorkParamRecord.Dto.Output;

namespace ZhonTai.Industry.Services.AlarmRecord
{
    /// <summary>
    /// 告警监控服务
    /// </summary>
    [DynamicApi(Area = IndustryConsts.AreaName)]
    public class AlarmRecordService : BaseService, IAlarmRecordService, IDynamicApi, ICapSubscribe
    {
        private readonly IAlarmRecordRepository _alarmRecordRepository;
        private readonly IEHelper _iEHelper;
        private readonly IndustryLocalizer _industryLocalizer;

        public AlarmRecordService(IndustryLocalizer industryLocalizer, IEHelper iEHelper, IAlarmRecordRepository alarmRecordRepository)
        {
            _industryLocalizer = industryLocalizer;
            _iEHelper = iEHelper;
            _alarmRecordRepository = alarmRecordRepository;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        [HttpPost]
        public async Task<PageOutput<AlarmRecordGetPageOutput>> GetPageAsync(PageInput<AlarmRecordGetPageInput> input)
        {
            var filter = input.Filter;
            var tableNames = GetTableFilter(filter);
            long total = 0;
            List<AlarmRecordGetPageOutput> allRecords = new List<AlarmRecordGetPageOutput>();
            foreach (var tableName in tableNames)
            {
                var select = _alarmRecordRepository.Select
                .AsTable((type, old) =>
                {
                    if (type == typeof(AlarmRecordEntity))
                        return tableName;
                    if (type == typeof(WorkStationEntity))
                        return "cfg_work_station";
                    return old;
                })
                .WhereDynamicFilter(input.DynamicFilter)
                .WhereIf(filter.StartTime != null, x => x.CreatedTime >= filter.StartTime)
                .WhereIf(filter.EndTime != null, x => x.CreatedTime <= filter.EndTime)
                .WhereIf(filter.StationId.HasValue && filter.StationId > 0, w => w.StationId == filter.StationId)
                .Count(out var count);
                if (input.SortList != null && input.SortList.Count > 0)
                {
                    input.SortList.ForEach(sort =>
                    {
                        select = select.OrderByPropertyNameIf(sort.Order.HasValue, sort.PropName, sort.IsAscending.Value);
                    });
                }
                else
                {
                    select = select.OrderByDescending(a => a.Id);
                }
                var list = await select.OrderByDescending(c => c.Id)
                 .Page(input.CurrentPage, input.PageSize)
                 .ToListAsync(t =>
                 new AlarmRecordGetPageOutput()
                 {
                     StationCode = t.WorkStation.StationCode,
                     StationName = t.WorkStation.StationName,
                     LineCode = t.WorkStation.ProductionLine.LineCode,
                     LineName = t.WorkStation.ProductionLine.LineName,
                 });
                total += count;
                allRecords.AddRange(list);
            }
            var data = new PageOutput<AlarmRecordGetPageOutput> { List = allRecords, Total = total };
            return data;
        }

        /// <summary>
        /// 报警存储
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        [NonAction]
        [CapSubscribe("AlarmMonitor")]
        public async Task AddMoreAsync(List<AlarmMessage> input)
        {
            var entitys = input.Select(s =>
             {
                 return new AlarmRecordEntity()
                 {
                     StationId = s.stationId,
                     AlarmCode = s.AlarmCode,
                     StartTime = s.StartTime,
                     EndTime = s.EndTime,
                     CycleTime = (s.EndTime - s.StartTime).TotalSeconds,
                     Description = s.Description
                 };
             }).ToList();
            await _alarmRecordRepository.InsertAsync(entitys);
        }

        /// <summary>
        /// 导出数据
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [NonFormatResult]
        public async Task<ActionResult> ExportDataAsync(ExportInput input)
        {
            using var _ = _alarmRecordRepository.DataFilter.DisableAll();
            var select = _alarmRecordRepository.Select;
            select = select.OrderByDescending(o => o.Id);
            var dataList = await select.WhereDynamicFilter(input.DynamicFilter).ToListAsync(t => new AlarmRecordExport()
            {
                StationCode = t.WorkStation.StationCode,
                StationName = t.WorkStation.StationName,
                LineCode = t.WorkStation.ProductionLine.LineCode,
                LineName = t.WorkStation.ProductionLine.LineName,
            });
            //导出数据
            var fileName = input.FileName.NotNull() ? input.FileName : _industryLocalizer["告警记录-{0}列表{1}.xlsx", _industryLocalizer["告警记录"], DateTime.Now.ToString("yyyyMMddHHmmss")];
            return await _iEHelper.ExportDataAsync(dataList, fileName, _industryLocalizer["告警记录"]);
        }

        /// <summary>
        /// 动态分表策略生成器
        /// </summary>
        private List<string> GetTableFilter(AlarmRecordGetPageInput filter)
        {
            const string baseTableName = "prd_alarm_record";
            IEnumerable<string> GetShardingTables(DateTime start, DateTime end)
            {
                for (var month = start; month <= end; month = month.AddMonths(1))
                {
                    yield return $"{baseTableName}_{month:yyyyMM}";
                }
            }
            if (filter?.StartTime != null || filter?.EndTime != null)
            {
                var start = filter.StartTime?.Date ?? DateTime.MinValue;
                var end = filter.EndTime?.Date ?? new DateTime(9999, 12, 31);
                end = end.AddMonths(1).AddDays(-1);
                return GetShardingTables(start, end).Distinct().Reverse().ToList();
            }
            else
            {
                const int recentMonths = 1;
                var recentTables = Enumerable.Range(0, recentMonths)
                    .Select(i => DateTime.Now.AddMonths(-i))
                    .OrderByDescending(d => d) // 按时间倒序
                    .Select(d => $"{baseTableName}_{d:yyyyMM}");

                return recentTables.ToList();
            }
        }
    }
}